/* 
 * File:   Main.cpp
 * Author: arkadiusz
 *
 * Created on 9 marzec 2009, 11:38
 */

#include <stdlib.h>
//#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <opencv/cv.h>
#include <opencv/cxcore.h>
#include <opencv/highgui.h>
using namespace std;

vector< vector<int> > wczytajMAT(string);
void rysuj(vector< vector<int> >, string);
void rysujN(vector< vector<int> > m, string scieszka, int n);
vector< vector<int> > getMatrixFromIplImage(IplImage* image);
IplImage* getIplImageFromMatrix(vector< vector<int> > grayMatrix, int n);
void generuj(vector< vector<int> > m, string scieszka, int MAX);
const int maxI = 181;
const int maxJ = 297;

/*
 * 
 */
int main(int argc, char** argv) {
    int start = clock();
    string katalog("/home/arkadiusz/Dokumenty/IPPT/skany/obszary040309/");
    string plikMAT("areas-writelog-2006-11-15-09-38-log.mat");
    string plikPTS("areas-writelog-2006-11-15-09-38-log.pts");


    string nazwaBaz("Obraz");

    vector< vector<int> > macierz = wczytajMAT(katalog + plikMAT);
    vector< vector<int> > matSum;

    matSum.resize(maxJ);
    for (int j = 0; j < matSum.size(); j++) {
        matSum[j].resize(maxI);
    }
    //==============================
    for (int nn = 1; nn < 10; nn++) {
        string plikPBMn = nazwaBaz;
        plikPBMn += ('0' + nn);
        plikPBMn += ".pbm";
        cout << plikPBMn << endl;

        //IplImage* obrazWejn = getIplImageFromMatrix(macierz, nn);
        rysujN(macierz, (katalog + plikPBMn).c_str(), nn);
        //cvSaveImage((katalog + plikPBMn).c_str(),obrazWejn);
        IplImage* obrazWejn = cvLoadImage((katalog + plikPBMn).c_str());
        //cvSaveImage((katalog + plikPBMn + "XX.png").c_str(),obrazWejn);
        IplImage* obrazSza = cvCreateImage(cvGetSize(obrazWejn), IPL_DEPTH_8U, 1);
        IplImage* obrazErode = cvCreateImage(cvGetSize(obrazWejn), IPL_DEPTH_8U, 1);
        IplImage* obrazWyn8u = cvCreateImage(cvGetSize(obrazWejn), IPL_DEPTH_8U, 1);


        //cvSmooth(obrazWejn, obrazWejn, CV_BLUR, 3, 3);
        //cvThreshold(obrazWejn, obrazWejn, 128, 255, CV_THRESH_BINARY);
        cvSmooth(obrazWejn, obrazWejn, CV_MEDIAN, 3);
        cvCvtColor(obrazWejn, obrazSza, CV_BGR2GRAY);
        //cvCanny(obrazSza, obrazWyn8u, 0, 1, 3);
        cvErode(obrazSza, obrazErode);
        cvAbsDiff(obrazSza, obrazErode, obrazWyn8u);

        cvSaveImage((katalog + plikPBMn + "Kraw.png").c_str(), obrazWyn8u);
        vector< vector<int> > matnn = getMatrixFromIplImage(obrazWyn8u);
        cout << "macierz: " << macierz.size() << " x " << macierz[0].size() << endl;
        cout << "matnn: " << matnn.size() << " x " << matnn[0].size() << endl;
        cout << "matSum: " << matSum.size() << " x " << matSum[0].size() << endl;

        for (int i = 0; i < maxI; i++)
            for (int j = 0; j < maxJ; j++) {
                if (matnn[i][j] != 0) matSum[i][j] = nn;
            }
    }//+=+

    rysuj(matSum, katalog + "WYNIK.pbm");
    generuj(matSum, katalog + plikMAT + ".az", 10);


    int finish = clock();
    double duration = (double) ((finish - start) * 1000) / CLOCKS_PER_SEC;
    cout << "\nCzas = " << duration << "ms\n";
    return (EXIT_SUCCESS);
}
//==============================================================================

/**
 *
 */
vector< vector<int> >
wczytajMAT(string scieszka) {

    ifstream plik(scieszka.c_str());
    vector< vector<int> > M;

    //konfiguruje wektor-kolumne tak, zeby miescil size wektorów-wiersze
    M.resize(maxI);
    //konfiguruje wektory-wiersze tak, aby kazdy zmiescil size+1 liczb
    for (int x = 0; x < M.size(); x++) {
        M[x].resize(maxJ);
    }
    string wiersz;
    while (getline(plik, wiersz)) {
        //pomijamy komentarze
        if (wiersz.find("#") != string::npos) continue;
        //
        stringstream ssWiersz(wiersz);
        int i, j, k;
        ssWiersz >> i >> j >> k;
        M[i][j] = k;
    }//while

    return M;
}
//==============================================================================

void rysujN(vector< vector<int> > m, string scieszka, int n) {

    FILE* f = fopen(scieszka.c_str(), "w");
    fclose(f);
    fstream plik(scieszka.c_str(), ios::in | ios::out);
    if (plik.fail()) { //nie ma pliku
        cout << "Brak Pliku!" << endl;
    }
    plik << "P2" << endl;
    int W = m.size();
    int K = m[0].size();
    plik << K << " " << W << endl;
    //plik << maxObszar << endl;
    plik << 2 << endl;

    for (int w = 0; w < W; w++) {
        for (int k = 0; k < K; k++) {
            if (m[w][k] == n)
                plik << "1 ";
            else
                plik << "0 ";
        }
        plik << endl;
    }
    plik.close();

}
//==============================================================================

void generuj(vector< vector<int> > m, string scieszka, int MAX) {

    FILE* f = fopen(scieszka.c_str(), "w");
    fclose(f);
    fstream plik(scieszka.c_str(), ios::out | ios::ate);
    if (plik.fail()) { //nie ma pliku
        cout << "Brak Pliku!" << endl;
    }
    for (int N = 1; N < MAX; N++) {
        plik << N << endl;
        //cout<< N << endl;
        for (int w = 0; w < m.size(); w++) {
            for (int k = 0; k < m[w].size(); k++) {
                if (m[w][k] == N) {
                    plik << w << " " << k << endl;
                }
            }
        }
    }
    plik.close();

}

void rysuj(vector< vector<int> > m, string scieszka) {

    FILE* f = fopen(scieszka.c_str(), "w");
    fclose(f);
    fstream plik(scieszka.c_str(), ios::in | ios::out);
    if (plik.fail()) { //nie ma pliku
        std::cout << "Brak Pliku!" << endl;
    }
    plik << "P2" << endl;
    int maxObszar = 0;
    for (int w = 0; w < m.size(); w++) {
        for (int k = 0; k < m[w].size(); k++) {
            if (maxObszar < m[w][k]) maxObszar = m[w][k];
        }
    }
    plik << maxJ << " " << maxI << endl;
    //plik << maxObszar << endl;
    plik << 100 << endl;

    for (int w = 0; w < m.size(); w++) {
        for (int k = 0; k < m[w].size(); k++) {
            plik << (m[w][k] > 9 ? 0 : m[w][k]) << " ";
            //plik << "x";
        }
        plik << endl;
    }
    plik.close();

}

//==============================================================================

vector< vector<int> >
getMatrixFromIplImage(IplImage* image) {
    vector< vector<int> > mat;
    //formowanie macierzy
    mat.resize(image->width);
    for (int j = 0; j < mat.size(); j++) {
        mat[j].resize(image->height);
    }

    CvScalar s;
    for (int i = 0; i < image->width; i++)
        for (int j = 0; j < image->height; j++) {
            s = cvGet2D(image, image->height - j - 1, i);
            mat[i][j] = s.val[0];
        }
    return mat;
}

IplImage* getIplImageFromMatrix(vector<vector <int> > grayMatrix, int n) {
    int sy = grayMatrix.size(), sx = grayMatrix[0].size();
    // 1 kanał, 8bit:
    IplImage* img = cvCreateImage(cvSize(sx, sy), IPL_DEPTH_8U, 1);
    // efektywność można poprawić używając bezpośrednich wskaźników, ale
    // w tym momencie to zbędne...
    CvScalar s = cvScalar(0);
    for (int i = 0; i < sx; i++)
        for (int j = 0; j < sy; j++) {
            s.val[0] = grayMatrix[i][j];
            if (grayMatrix[i][j] == n) cvSet2D(img, sy - j - 1, i, s); // odwrotne indeksy!
        }
    return img;
}
